<template>
  <div class="ssh-terminal-tab">
    <!-- 连接状态栏 -->
    <div class="status-bar" v-if="showStatusBar">
      <div class="status-info">
        <el-icon :class="getStatusClass(connectionStatus)">
          <component :is="getStatusIcon(connectionStatus)" />
        </el-icon>
        <span class="status-text">{{ getStatusText(connectionStatus) }}</span>
        <span class="host-info">{{ host.hostname }} ({{ host.ip_address }})</span>
      </div>
      <div class="status-actions">
        <el-button
          v-if="connectionStatus === 'disconnected' || connectionStatus === 'error'"
          size="small"
          type="primary"
          @click="reconnect"
        >
          重连
        </el-button>
        <el-button
          v-if="connectionStatus === 'connected'"
          size="small"
          @click="disconnect"
        >
          断开
        </el-button>
        <el-button size="small" @click="toggleStatusBar">
          {{ showStatusBar ? '隐藏' : '显示' }}状态栏
        </el-button>
      </div>
    </div>

    <!-- 终端容器 -->
    <div class="terminal-container" :class="{ 'with-status-bar': showStatusBar }">
      <div ref="terminalElement" class="terminal-element"></div>
      
      <!-- 连接覆盖层 -->
      <div v-if="showConnectionOverlay" class="connection-overlay">
        <div class="connection-message">
          <el-icon class="loading-icon">
            <Loading />
          </el-icon>
          <span>{{ connectionMessage }}</span>
        </div>
      </div>
    </div>
  </div>
</template>

<script setup>
import { ref, onMounted, onUnmounted, nextTick, watch } from 'vue'
import { ElMessage } from 'element-plus'
import { Loading, CircleCheck, CircleClose, Connection } from '@element-plus/icons-vue'
import { Terminal } from '@xterm/xterm'
import { FitAddon } from '@xterm/addon-fit'
import { WebLinksAddon } from '@xterm/addon-web-links'
import '@xterm/xterm/css/xterm.css'

// Props
const props = defineProps({
  host: {
    type: Object,
    required: true
  },
  tabId: {
    type: String,
    required: true
  },
  autoConnect: {
    type: Boolean,
    default: true
  }
})

// Emits
const emit = defineEmits(['status-change', 'title-change'])

// 响应式数据
const terminalElement = ref()
const connectionStatus = ref('disconnected')
const connectionMessage = ref('')
const showStatusBar = ref(true)

// 终端相关
let terminal = null
let fitAddon = null
let websocket = null
let heartbeatInterval = null
let reconnectAttempts = 0
const maxReconnectAttempts = 3

// 心跳检测相关
const lastHeartbeatTime = ref(0)
const heartbeatFailCount = ref(0)
const maxHeartbeatFails = 3

// 计算属性
const showConnectionOverlay = ref(false)

// 会话ID（用于标识真正的SSH连接）
const sessionId = ref(null)

// 监听器
watch(() => connectionStatus.value, (newStatus) => {
  emit('status-change', props.tabId, newStatus, sessionId.value)

  // 根据连接状态显示/隐藏覆盖层
  showConnectionOverlay.value = newStatus === 'connecting'

  // 更新连接消息
  updateConnectionMessage(newStatus)
})

// 生命周期
onMounted(async () => {
  await nextTick()
  initTerminal()
  
  if (props.autoConnect) {
    connectWebSocket()
  }
})

onUnmounted(() => {
  cleanup()
})

// 方法定义
const initTerminal = () => {
  if (!terminalElement.value) return

  // 创建终端实例
  terminal = new Terminal({
    cursorBlink: true,
    cursorStyle: 'block',
    fontSize: 14,
    fontFamily: 'Monaco, Menlo, "Ubuntu Mono", "Consolas", "Courier New", monospace',
    theme: {
      background: '#1e1e1e',
      foreground: '#ffffff',
      cursor: '#ffffff',
      selection: '#3e3e3e',
      black: '#000000',
      red: '#cd3131',
      green: '#0dbc79',
      yellow: '#e5e510',
      blue: '#2472c8',
      magenta: '#bc3fbc',
      cyan: '#11a8cd',
      white: '#e5e5e5',
      brightBlack: '#666666',
      brightRed: '#f14c4c',
      brightGreen: '#23d18b',
      brightYellow: '#f5f543',
      brightBlue: '#3b8eea',
      brightMagenta: '#d670d6',
      brightCyan: '#29b8db',
      brightWhite: '#e5e5e5'
    },
    allowTransparency: true,
    convertEol: true,
    scrollback: 1000,
    rows: 24,
    cols: 80
  })

  // 添加插件
  fitAddon = new FitAddon()
  terminal.loadAddon(fitAddon)
  terminal.loadAddon(new WebLinksAddon())

  // 打开终端
  terminal.open(terminalElement.value)

  // 适应容器大小 - 使用nextTick确保DOM更新完成
  nextTick(() => {
    setTimeout(() => {
      if (fitAddon && terminalElement.value) {
        try {
          fitAddon.fit()
          console.log(`[${props.tabId}] Terminal initialized with size ${terminal.cols}x${terminal.rows}`)
        } catch (error) {
          console.warn(`[${props.tabId}] Initial fit error:`, error)
        }
      }
    }, 200) // 增加延迟确保容器完全渲染
  })

  // 监听数据输入
  terminal.onData(data => {
    if (websocket && websocket.readyState === WebSocket.OPEN) {
      websocket.send(JSON.stringify({
        type: 'command',
        data: data
      }))
    }
  })

  // 监听终端大小变化
  terminal.onResize(({ cols, rows }) => {
    if (websocket && websocket.readyState === WebSocket.OPEN) {
      websocket.send(JSON.stringify({
        type: 'resize',
        cols: cols,
        rows: rows
      }))
    }
  })

  // 监听窗口大小变化
  window.addEventListener('resize', handleResize)
}

const connectWebSocket = () => {
  if (!props.host?.id) {
    ElMessage.error('主机信息无效')
    return
  }

  connectionStatus.value = 'connecting'
  reconnectAttempts++

  // 获取JWT token
  const token = localStorage.getItem('access_token')
  if (!token) {
    ElMessage.error('未找到认证token，请重新登录')
    connectionStatus.value = 'error'
    return
  }

  // 构建WebSocket URL
  const protocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:'
  const backendHost = process.env.NODE_ENV === 'development' ? 'localhost:8000' : window.location.host
  const wsUrl = `${protocol}//${backendHost}/ws/ssh/${props.host.id}/?token=${token}`

  console.log(`[${props.tabId}] 正在连接WebSocket:`, wsUrl)

  websocket = new WebSocket(wsUrl)

  websocket.onopen = () => {
    console.log(`[${props.tabId}] WebSocket连接已建立`)
    reconnectAttempts = 0
    startHeartbeat()
  }

  websocket.onmessage = (event) => {
    try {
      const data = JSON.parse(event.data)
      handleWebSocketMessage(data)
    } catch (error) {
      console.error(`[${props.tabId}] 解析WebSocket消息失败:`, error)
    }
  }

  websocket.onclose = (event) => {
    console.log(`[${props.tabId}] WebSocket连接已关闭`, event.code, event.reason)
    connectionStatus.value = 'disconnected'
    stopHeartbeat()

    // 自动重连逻辑
    if (event.code !== 1000 && reconnectAttempts < maxReconnectAttempts) {
      setTimeout(() => {
        console.log(`[${props.tabId}] 尝试自动重连 (${reconnectAttempts}/${maxReconnectAttempts})`)
        connectWebSocket()
      }, 2000 * reconnectAttempts)
    }
  }

  websocket.onerror = (error) => {
    console.error(`[${props.tabId}] WebSocket错误:`, error)
    connectionStatus.value = 'error'
  }
}

const handleWebSocketMessage = (data) => {
  switch (data.type) {
    case 'output':
      if (terminal) {
        terminal.write(data.data)
      }
      break

    case 'status':
      if (data.status === 'connected') {
        connectionStatus.value = 'connected'
        // 设置会话ID（用于标识真正的SSH连接）
        sessionId.value = data.session_id || `${props.tabId}_${Date.now()}`

        if (data.message && terminal) {
          terminal.writeln(`\r\n${data.message}\r\n`)
        }
      } else if (data.status === 'failed') {
        connectionStatus.value = 'error'
        sessionId.value = null
        if (data.message && terminal) {
          terminal.writeln(`\r\n连接失败: ${data.message}\r\n`)
        }
      }
      break

    case 'pong':
      // 处理心跳响应
      handleHeartbeatResponse(data)
      break

    default:
      console.log(`[${props.tabId}] 未知消息类型:`, data.type)
  }
}

const handleHeartbeatResponse = (data) => {
  const now = Date.now()
  const latency = data.timestamp ? now - data.timestamp : 0

  // 更新连接状态
  if (data.status === 'connected') {
    connectionStatus.value = 'connected'
    lastHeartbeatTime.value = now
    heartbeatFailCount.value = 0

    // 记录延迟信息
    if (latency > 0) {
      console.log(`[${props.tabId}] 心跳延迟: ${latency}ms`)
    }
  } else if (data.status === 'disconnected' || data.status === 'error') {
    connectionStatus.value = 'disconnected'
    heartbeatFailCount.value++

    console.warn(`[${props.tabId}] 心跳检测失败 (${heartbeatFailCount.value}次):`, data.error || '连接断开')

    // 如果连续失败多次，尝试重连
    if (heartbeatFailCount.value >= maxHeartbeatFails) {
      console.log(`[${props.tabId}] 连续心跳失败，尝试重连...`)
      attemptReconnect()
    }
  }
}

const attemptReconnect = () => {
  if (websocket) {
    websocket.close()
  }

  // 重置计数器
  heartbeatFailCount.value = 0

  // 延迟重连
  setTimeout(() => {
    console.log(`[${props.tabId}] 开始重连...`)
    connectWebSocket()
  }, 2000)
}

const startHeartbeat = () => {
  // 可配置的心跳间隔，默认15秒
  const heartbeatInterval_ms = 15000 // 15秒心跳，更及时的连接检测

  heartbeatInterval = setInterval(() => {
    if (websocket && websocket.readyState === WebSocket.OPEN) {
      websocket.send(JSON.stringify({
        type: 'ping',
        timestamp: Date.now() // 添加时间戳用于延迟检测
      }))
    }
  }, heartbeatInterval_ms)
}

const stopHeartbeat = () => {
  if (heartbeatInterval) {
    clearInterval(heartbeatInterval)
    heartbeatInterval = null
  }
}

// 防抖处理resize事件
let resizeTimeout = null

const handleResize = () => {
  // 清除之前的定时器
  if (resizeTimeout) {
    clearTimeout(resizeTimeout)
  }

  // 防抖处理，避免频繁resize
  resizeTimeout = setTimeout(() => {
    try {
      if (fitAddon && terminal && terminalElement.value) {
        // 确保终端容器可见且有尺寸
        const container = terminalElement.value
        if (container.offsetWidth > 0 && container.offsetHeight > 0) {
          fitAddon.fit()

          // 强制刷新终端显示
          if (terminal.rows > 0 && terminal.cols > 0) {
            terminal.refresh(0, terminal.rows - 1)
          }

          console.log(`[${props.tabId}] Terminal resized to ${terminal.cols}x${terminal.rows}`)
        }
      }
    } catch (error) {
      console.warn(`[${props.tabId}] Resize error:`, error)
    }
  }, 150) // 增加防抖延迟
}

const reconnect = () => {
  if (websocket) {
    websocket.close()
  }
  
  reconnectAttempts = 0
  setTimeout(() => {
    connectWebSocket()
  }, 500)
}

const disconnect = () => {
  if (websocket) {
    websocket.close(1000, 'User disconnected')
  }
  connectionStatus.value = 'disconnected'
  sessionId.value = null
}

const toggleStatusBar = () => {
  showStatusBar.value = !showStatusBar.value
  setTimeout(() => {
    handleResize()
  }, 100)
}

const cleanup = () => {
  window.removeEventListener('resize', handleResize)
  stopHeartbeat()

  // 清理resize定时器
  if (resizeTimeout) {
    clearTimeout(resizeTimeout)
    resizeTimeout = null
  }

  if (websocket) {
    websocket.close()
  }

  if (terminal) {
    terminal.dispose()
  }
}

// 状态相关方法
const getStatusClass = (status) => {
  return `status-${status}`
}

const getStatusIcon = (status) => {
  const icons = {
    connected: CircleCheck,
    connecting: Loading,
    disconnected: CircleClose,
    error: CircleClose
  }
  return icons[status] || CircleClose
}

const getStatusText = (status) => {
  const texts = {
    connected: '已连接',
    connecting: '连接中',
    disconnected: '未连接',
    error: '连接错误'
  }
  return texts[status] || '未知状态'
}

const updateConnectionMessage = (status) => {
  const messages = {
    connecting: `正在连接到 ${props.host.hostname}...`,
    connected: '连接成功',
    disconnected: '连接已断开',
    error: '连接失败'
  }
  connectionMessage.value = messages[status] || ''
}

// 暴露方法给父组件
defineExpose({
  reconnect,
  disconnect,
  fitTerminal: () => {
    handleResize() // 使用优化后的resize处理
  }
})
</script>

<style scoped>
.ssh-terminal-tab {
  height: 100%;
  display: flex;
  flex-direction: column;
  background-color: #1e1e1e;
}

.status-bar {
  background-color: #2d2d2d;
  padding: 8px 16px;
  display: flex;
  justify-content: space-between;
  align-items: center;
  border-bottom: 1px solid #444;
  color: #ffffff;
  font-size: 12px;
}

.status-info {
  display: flex;
  align-items: center;
  gap: 8px;
}

.status-actions {
  display: flex;
  gap: 8px;
}

.host-info {
  color: #909399;
  margin-left: 8px;
}

.terminal-container {
  flex: 1;
  position: relative;
  overflow: hidden;
  min-height: 0; /* 确保flex子元素能正确缩放 */
}

.terminal-container.with-status-bar {
  /* 为状态栏预留空间 */
}

.terminal-element {
  width: 100%;
  height: 100%;
  padding: 10px;
  box-sizing: border-box; /* 确保padding不影响尺寸计算 */
  resize: none; /* 防止用户手动调整大小 */
}

.connection-overlay {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background-color: rgba(0, 0, 0, 0.8);
  display: flex;
  justify-content: center;
  align-items: center;
  z-index: 10;
}

.connection-message {
  display: flex;
  align-items: center;
  gap: 12px;
  color: #ffffff;
  font-size: 14px;
}

.loading-icon {
  animation: spin 1s linear infinite;
}

@keyframes spin {
  from { transform: rotate(0deg); }
  to { transform: rotate(360deg); }
}

/* 状态图标样式 */
.status-connected {
  color: #67c23a;
}

.status-connecting {
  color: #e6a23c;
  animation: pulse 1.5s infinite;
}

.status-disconnected {
  color: #909399;
}

.status-error {
  color: #f56c6c;
}

@keyframes pulse {
  0%, 100% { opacity: 1; }
  50% { opacity: 0.5; }
}

/* 覆盖xterm.js的默认样式 */
:deep(.xterm) {
  height: 100% !important;
}

:deep(.xterm-viewport) {
  background-color: transparent !important;
}

:deep(.xterm-screen) {
  background-color: transparent !important;
}
</style>
